package com.smart.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.smart.common.config.HttpClientTemplate;
import com.smart.common.config.WatchesConfig;
import com.smart.common.constant.GlobalConstants;
import com.smart.common.core.domain.R;
import com.smart.common.enums.DeviceActionEnum;
import com.smart.common.exception.ServiceException;
import com.smart.common.utils.DateUtils;
import com.smart.common.utils.StringUtils;
import com.smart.common.utils.bean.BeanUtils;
import com.smart.common.utils.file.FileUtils;
import com.smart.system.domain.*;
import com.smart.system.domain.dto.*;
import com.smart.system.domain.enums.AlarmType;
import com.smart.system.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class WatchesServiceImpl implements IWatchesService {
    @Autowired
    private WatchesConfig watchesConfig;

    @Autowired
    private HttpClientTemplate httpClientTemplate;

    @Autowired
    private IEmployeeTrajectoryService employeeTrajectoryService;

    @Autowired
    private IEmployeeService employeeService;

    @Autowired
    private IWorkingScheduleService workingScheduleService;

    @Autowired
    private IAreaEmployeeService areaEmployeeService;

    @Autowired
    private IAreaService areaService;

    @Autowired
    private IAttendanceRecordService attendanceRecordService;

    @Autowired
    private IAlarmService alarmService;

    @Autowired
    private IAudioService audioService;

    @Override
    public void sendInstruct(CommandRequest req) {
        DeviceActionEnum deviceActionEnum = DeviceActionEnum.fromCode(req.getCommand());
        switch (deviceActionEnum) {
            case REMOTE_LOCATION:
                // 执行远程立即定位操作
                Map params = new HashMap<String,String>();
                params.put("deviceid", req.getDeviceid());
                params.put("command", String.valueOf(req.getCommand()));
                String s = httpClientTemplate.doGet(watchesConfig.getSendInstructionsUrl(),params);
                System.out.println("执行远程立即定位操作:"+s);
                break;
            case REMOTE_HEART_RATE:
                // 执行远程测量心率操作
                System.out.println("执行远程测量心率操作");
                break;
            case REMOTE_SHUTDOWN:
                // 执行远程关机操作
                System.out.println("执行远程关机操作");
                break;
            case REMOTE_BLOOD_PRESSURE:
                // 执行远程测量血压操作
                System.out.println("执行远程测量血压操作");
                break;
            case REMOTE_TEMPERATURE:
                // 执行远程测量体温操作
                System.out.println("执行远程测量体温操作");
                break;
            case SEND_VOICE_TO_WATCH:
                // 执行下发语音到手表操作
                Map sendParams = new HashMap<String,String>();
                sendParams.put("deviceid", req.getDeviceid());
                sendParams.put("command", String.valueOf(req.getCommand()));
                sendParams.put("cmdvalue", req.getCmdvalue());
                String sendRes = httpClientTemplate.doPostJson(watchesConfig.getSendAudio(),JSON.toJSONString(sendParams));
                System.out.println("执行下发语音到手表操作:"+sendRes);
                break;
            case SEND_TEXT_TO_WATCH:
                // 执行下发文字信息到手表操作
                System.out.println("执行下发文字信息到手表操作");
                break;
            case REMOTE_OXYGEN:
                // 执行远程测量血氧操作
                System.out.println("执行远程测量血氧操作");
                break;
            case SEND_BLOOD_PRESSURE_RESULT:
                // 执行下发血压学习后的测量结果给设备操作
                System.out.println("执行下发血压学习后的测量结果给设备操作");
                break;
            case SET_DO_NOT_DISTURB_TIME:
                // 执行设置免打扰时间操作
                System.out.println("执行设置免打扰时间操作");
                break;
            case REMOTE_RESTART:
                // 执行远程设备重启操作
                System.out.println("执行远程设备重启操作");
                break;
            case SEND_TWO_DIMENSIONAL_INFO:
                // 执行下发二维信息到设备操作
                System.out.println("执行下发二维信息到设备操作");
                break;
            case SET_PedomETER_WORK_TIME:
                // 执行设置计步器工作时间操作
                System.out.println("执行设置计步器工作时间操作");
                break;
            case SEND_HEART_ATTACK_WARNING:
                // 执行下发心梗预警信息操作
                System.out.println("执行下发心梗预警信息操作");
                break;
            case SEND_BRAIN_ATTACK_WARNING:
                // 执行下发脑梗预警信息操作
                System.out.println("执行下发脑梗预警信息操作");
                break;
            case SEDENTARY_REMINDER:
                // 执行久坐提醒设置操作
                System.out.println("执行久坐提醒设置操作");
                break;
            case SLEEP_TIME_SETTING:
                // 执行睡眠时间设置操作
                System.out.println("执行睡眠时间设置操作");
                break;
            case SET_BLUETOOTH_SCAN_PARAMS:
                // 执行设置蓝牙扫描参数操作
                System.out.println("执行设置蓝牙扫描参数操作");
                break;
            case FACTORY_RESET:
                // 执行恢复出厂设置操作
                System.out.println("执行恢复出厂设置操作");
                break;
            case SET_HEALTH_MEASUREMENT_BIAS:
                // 执行设置测量健康时的偏差参数操作
                System.out.println("执行设置测量健康时的偏差参数操作");
                break;
            case SEND_GLUCOSE_LEARNING_COMMAND:
                // 执行下发血糖学习指令操作
                System.out.println("执行下发血糖学习指令操作");
                break;
            case SEND_GLUCOSE_MEASUREMENT_COMMAND:
                // 执行下发血糖测量指令操作
                System.out.println("执行下发血糖测量指令操作");
                break;
            case QUICK_DIAL_COMMAND:
                // 执行快捷拨号指令操作
                System.out.println("执行快捷拨号指令操作");
                break;
            case FIND_DEVICE:
                // 执行查找设备操作
                System.out.println("执行查找设备操作");
                break;
            default:
                throw new IllegalArgumentException("Unsupported action: " + deviceActionEnum);
        }
    }

    @Override
    public void updateDevice(DeviceSettingsDto dto) {
        // 执行远程立即定位操作
        System.out.println("设备配置参数修改");
        Map params = new HashMap<String,String>();
        params.put("deviceid", dto.getDeviceid());
        //设置定位间隔时间
        if (dto.getLocationtimeinterval()!=null) {
            params.put("locationtimeinterval", dto.getLocationtimeinterval());
        }
        //设置心率间隔时间
        if (dto.getHeartratetimeinterval()!=null) {
            params.put("heartratetiminterval", dto.getHeartratetimeinterval());
        }
        //设置血压间隔时间
        if (dto.getBpi()!=null) {
            params.put("bpi", dto.getBpi());
        }
        //设置体温间隔时间
        if (dto.getTpi()!=null) {
            params.put("tpi", dto.getTpi());
        }
        //设置血氧间隔时间
        if (dto.getOxi()!=null) {
            params.put("oxi", dto.getOxi());
        }
        String s = httpClientTemplate.doGet(watchesConfig.getSetUrl(),params);
        System.err.println("返回数据:"+s);
    }

    @Override
    public Integer getDeviceOnline(String deviceid) {
        Map params = new HashMap<String,String>();
        params.put("deviceid", deviceid);
        String s = httpClientTemplate.doGet(watchesConfig.getOnlineUrl(), params);
        R r = JSON.parseObject(s, R.class);
        return R.isSuccess(r)?0:1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitLocation(HttpServletRequest request) throws Exception {
        LocationInfo location = BeanUtils.create(LocationInfo.class, request);

        // 获取用户数据
        Employee employee = employeeService.getOne(Wrappers.lambdaQuery(Employee.class).eq(Employee::getImei, location.getDeviceid()));
        if (employee == null) {
            throw new ServiceException("Employee not found for device: " + location.getDeviceid());
        }

        // 创建员工轨迹记录
        EmployeeTrajectory employeeTrajectory = new EmployeeTrajectory();
        employeeTrajectory.setDeptId(employee.getDeptId());
        employeeTrajectory.setUserId(employee.getId());

        AreaLocation areaLocation = new AreaLocation();
        areaLocation.setLatitude(String.valueOf(location.getLatitude()));
        areaLocation.setLongitude(String.valueOf(location.getLongitude()));

        // 如果与上次数据波动较小,则认为没有移动
        EmployeeTrajectory lastPoint = employeeTrajectoryService.getOne(
                Wrappers.lambdaQuery(EmployeeTrajectory.class)
                        .eq(EmployeeTrajectory::getUserId, employee.getId())
                        .orderByDesc(EmployeeTrajectory::getCreateTime)
                        .last("limit 1"),
                false
        );

        if (lastPoint != null) {
            employeeTrajectory.setAreaLocation(
                    AreaLocation.filterGpsPoint(
                            lastPoint.getAreaLocation(),
                            areaLocation,
                            GlobalConstants.EMPLOYEE_LOCATION_THRESHOLD_VALUE
                    )
            );
        } else {
            employeeTrajectory.setAreaLocation(areaLocation);
        }

        employeeTrajectoryService.insertEmployeeTrajectory(employeeTrajectory);

        // 检查区域告警
        AreaEmployee areaEmployee = areaEmployeeService.getOne(
                Wrappers.lambdaQuery(AreaEmployee.class)
                        .eq(AreaEmployee::getEmployeeId, employee.getId())
                        .last("limit 1"),
                false
        );

        if (areaEmployee == null) {
            return;
        }

        Area area = areaService.selectAreaById(areaEmployee.getAreaId());
        if (area == null) {
            return;
        }

        WorkingSchedule workingSchedule = workingScheduleService.getWorkingSchedule(employee.getDeptId());
        if (workingSchedule == null) {
            return;
        }

        // 判断排班是否在区间内
        if (!workingSchedule.isWorkDay()) {
            return;
        }

        // 判断当前用户是否是上班时间
        if (!workingSchedule.isWorkingUpTime()) {
            return;
        }

        // 判断用户今天是否上班打卡,如果没有打卡,则不作记录
        AttendanceRecord attendanceRecord = attendanceRecordService.getOne(
                Wrappers.lambdaQuery(AttendanceRecord.class)
                        .apply("attendance_date = {0}", DateUtils.getDate())
                        .last("limit 1"),
                false
        );

        if (attendanceRecord == null || !attendanceRecord.isAttendanceWork()) {
            return;
        }

        // 判断用户是否在区域中
        if (area.isContains(String.valueOf(location.getLongitude()), String.valueOf(location.getLatitude()))) {
            return;
        }

        // 判断是否存在同类型,并且未读的告警
        Alarm alarm = alarmService.getOne(
                Wrappers.lambdaQuery(Alarm.class)
                        .eq(Alarm::getType, Alarm.EMPLOYEE)
                        .eq(Alarm::getToId, employee.getId())
                        .eq(Alarm::getStatus, GlobalConstants.YES_CHECKED)
                        .last("limit 1")
        );

        if (alarm == null) {
            // 获取用户区域
            alarmService.save(Alarm.getByMessage(Alarm.Message.OUT_OF_AREA, Alarm.EMPLOYEE, employee.getId(), areaEmployee.getAreaId()));
        }
    }

    @Override
    public void sensor(DeviceDataDto andSet) {
        Employee one = employeeService.getOne(Wrappers.lambdaQuery(Employee.class).eq(Employee::getImei, andSet.getDeviceid()).last("limit 1"));
        if(one == null){
            return;
        }
        LambdaUpdateWrapper<Employee> update = Wrappers.lambdaUpdate(Employee.class);
        update.eq(Employee::getImei, andSet.getDeviceid());
        update.set(andSet.getHeart()!=null,Employee::getHeart, andSet.getHeart());
        update.set(andSet.getTemperature()!=null,Employee::getTemperature, andSet.getTemperature());
        update.set(andSet.getSystolic()!=null,Employee::getSystolic, andSet.getSystolic());
        update.set(andSet.getDiastolic()!=null,Employee::getDiastolic, andSet.getDiastolic());
        update.set(andSet.getOx()!=null,Employee::getOx, andSet.getOx());
        update.set(andSet.getBattery()!=null,Employee::getBattery, andSet.getBattery());
        Integer battery = GlobalConstants.BATTERY;
        if(one.getBatteryCapacity()!=null&& !one.getBatteryCapacity().equals("")){
            battery = Integer.parseInt(one.getBatteryCapacity());
        }
        //获取人员所属区域
        AreaEmployee areaEmployee = areaEmployeeService.getOne(Wrappers.lambdaQuery(AreaEmployee.class).eq(AreaEmployee::getEmployeeId, one.getId()).last("limit 1"),false);
        //电量过低的话,需要插入低电量警告
        if(andSet.getBattery()!=null&&Integer.parseInt(andSet.getBattery())<=battery){
            //插入低电量警告
            if (areaEmployee!=null) {
                //查询是否存在同类型未读告警
                Alarm alarm = alarmService.getOne(Wrappers.lambdaQuery(Alarm.class)
                        .eq(Alarm::getType, Alarm.EMPLOYEE)
                        .eq(Alarm::getToId, one.getId())
                        .eq(Alarm::getStatus, GlobalConstants.YES_CHECKED)
                        .last("limit 1"));
                if (alarm == null) {
                    alarmService.save(Alarm.getByMessage(Alarm.Message.LOW_CHARGE, Alarm.EMPLOYEE, one.getId(),areaEmployee.getAreaId()));
                }
            }
        }
        if (andSet.getHeart() != null || andSet.getTemperature() != null || andSet.getSystolic() != null || andSet.getDiastolic() != null || andSet.getOx() != null || andSet.getBattery() != null) {
            employeeService.update(update);
        }
    }

    @Override
    public int chat(Watches params) {
        Employee one = employeeService.getOne(Wrappers.lambdaQuery(Employee.class).eq(Employee::getImei, params.getDeviceid()));
        if(one == null){
            return 0;
        }
        Audio audio = Audio.builder()
                .employeeId(one.getId())
                .toEmployeeId(0)
                .type(GlobalConstants.CHAT)
                .body(params.getAudio())
                .createTime(new Date())
                .build();
        audioService.save(audio);
        return 1;
    }

    @Override
    public boolean setSos(String imei, String sos1, String sos2, String sos3) {
        HashMap<String, String> params = new HashMap<>();
        params.put("imei", imei);
        params.put("sos1", sos1);
        params.put("sos2", sos2);
        params.put("sos3", sos3);
        String s = httpClientTemplate.doGet(watchesConfig.getSetUrl(),params);
        if (s!=null&& StringUtils.contains(s,"200")) {
            return true;
        }else{
            throw new ServiceException(s);
        }
    }

    @Override
    public boolean setDevice(DeviceSettingsDto dto) {
        String s = httpClientTemplate.doGet(watchesConfig.getSetUrl(),dto.toMap());
        if (s!=null&& StringUtils.contains(s,"200")) {
            return true;
        }else{
            throw new ServiceException(s);
        }
    }

    @Override
    public boolean police(DeviceDataDtoPolice police) {
        Employee byImei = employeeService.getByImei(police.getDeviceid());
        if(byImei==null){
            return false;
        }
        //获取该用户的区域
        AreaEmployee one = areaEmployeeService.getOne(Wrappers.lambdaQuery(AreaEmployee.class).eq(AreaEmployee::getEmployeeId, byImei.getId()).last("limit 1"));
        if(one==null)return false;
        //SOS
        if (GlobalConstants.SOS_ALARM==police.getType()) {
            alarmService.save(Alarm.getByMessage(Alarm.Message.SOS_ALARM, Alarm.EMPLOYEE, byImei.getId(),one.getAreaId(), JSON.toJSONString(police)));
        }
//        //电量过低
//        if (Alarm.Message.LOW_CHARGE.getCode()==police.getType()) {
//            alarmService.save(Alarm.getByMessage(Alarm.Message.LOW_CHARGE, Alarm.EMPLOYEE, byImei.getId()));
//        }
        //心率异常
        if (GlobalConstants.HEART_RATE_ALARM==police.getType()) {
            alarmService.save(Alarm.getByMessage(Alarm.Message.HEART_RATE_ALARM, Alarm.EMPLOYEE, byImei.getId(),one.getAreaId()));
        }
        //血压异常
        if (GlobalConstants.BLOOD_PRESSURE_ALARM==police.getType()) {
            alarmService.save(Alarm.getByMessage(Alarm.Message.BLOOD_PRESSURE_ALARM, Alarm.EMPLOYEE, byImei.getId(),one.getAreaId()));
        }
        //血氧异常
        if (GlobalConstants.BLOOD_OXYGEN_ALARM==police.getType()) {
            alarmService.save(Alarm.getByMessage(Alarm.Message.BLOOD_OXYGEN_ALARM, Alarm.EMPLOYEE, byImei.getId(),one.getAreaId()));
        }
        //体温异常
        if (GlobalConstants.TEMPERATURE_ALARM==police.getType()) {
            alarmService.save(Alarm.getByMessage(Alarm.Message.TEMPERATURE_ALARM, Alarm.EMPLOYEE, byImei.getId(),one.getAreaId()));
        }
        return true;
    }
}
